/*
* Copyright (C) Microsoft. All rights reserved.  
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not 
* use this file except in compliance with the License.  You may obtain a copy 
* of the License at http://www.apache.org/licenses/LICENSE-2.0  
* 
* THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED 
* WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, 
* MERCHANTABLITY OR NON-INFRINGEMENT. 
*
* See the Apache License, Version 2.0 for specific language governing 
* permissions and limitations under the License.
*
*/
#pragma once

#include <baja/common.hpp>
#include <baja/app/app.hpp>
#include <baja/graphics.hpp>
#include <baja/graphics/scenes.hpp>
#include <baja/app/input.hpp>
#include <journal/models/interfaces.h>
#include <journal/views/interfaces.h>
#include <journal/common/settings_service.hpp>
#include <journal/views/paper_sheet_node.hpp>

namespace journal { namespace view {

namespace b = baja;
namespace g = baja::graphics;
namespace gs = baja::graphics::scenes;
namespace bs = baja::storage;

class page_curl
{
public:
    struct cone_parameters
    {
        cone_parameters() {}
        cone_parameters(b::float32 t, b::float32 a, b::float32 ang, b::float32 c) : theta(t), ay(a), angle(ang), conicContribution(c) {}
        b::float32 theta;				// angle of right-cone
        b::float32 ay;					// location on y axis of cone axis
        b::float32 angle;				// rotation about y axis
        b::float32 conicContribution;	// how much of (south tip cone == -1, cylinder == 0, north tip cone == 1)
    };

    enum class paper_type : b::uint32
    {
        looseLeaf,
        plasticCover
    };

    page_curl();
    static std::shared_ptr<page_curl> page_curl::create();
    void reset();
    void attachPage(const std::shared_ptr<paper_sheet_node> &pageNode, bool lastPage, paper_type paperType);
    void attachPage(const std::shared_ptr<ipage> &pageView, bool lastPage, paper_type paperType);	
    void startAutoCurl(bool firstTime);
    void startUserCurl(b::float32 x, b::float32 y);
    void debugCurlPage(cone_parameters cone);
    void onRender();
    bool stillCurling() { return _userCurl || _autoCurl; }
    bool shouldHideThisPage();
    b::float32 alphaValue();
    b::float32 progress();

private:
    
    cone_parameters paperParams(b::float32 x, b::float32 y);
    cone_parameters plasticParams(b::float32 x, b::float32 y);
    void curlPage(const std::shared_ptr<paper_sheet_node> &pageNode, cone_parameters cone);
    bool pageIsAttached() { return _pageNode != nullptr; }

    enum class pointerState
    {
        none,
        rightOfPage,
        onPage,
    };

    pointerState _pointerState;
    b::float32 _pageMinX;
    b::float32 _pageMaxX;
    b::float32 _pageMinY;
    b::float32 _pageMaxY;
    b::float32 _pageCoordTransform;
    bool _lastPage;
    b::int32 _numTicksInState;
    paper_type _paperType;

    bool _userCurl;
    bool _autoCurl;
    b::float32 _autoCurlStartTime;

    cone_parameters _currentCone;
    cone_parameters _nextCone;

    b::float32 _prevX[2];
    b::float32 _prevY[2];
    b::float32 _prevTimestamp[2];
    bool _userCurlingRight;

    std::shared_ptr<paper_sheet_node> _pageNode;
};

}} // namespace journal::view